import pandas as pd
import numpy as np
import matplotlib

matplotlib.use('Agg')
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.multioutput import MultiOutputRegressor
from sklearn.metrics import mean_squared_error
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号


def predict_weather():
    # --------------------- 数据加载与预处理 ---------------------
    df = pd.read_csv(r'F:\python\基于大数据的天气预测分析系统\model\weather1.csv')

    # 解析日期特征
    df['Date'] = pd.to_datetime(df['Date'])
    df['year'] = df['Date'].dt.year
    df['month'] = df['Date'].dt.month
    df['dow'] = df['Date'].dt.dayofweek
    df['dom'] = df['Date'].dt.day
    df['weekend'] = (df['dow'] >= 5).astype(int)

    # 添加时间序列特征
    for target in ['Temp1', 'Temp2']:
        for i in range(1, 4):  # 使用过去3天数据
            df[f'{target}_lag_{i}'] = df[target].shift(i)

    df = df.dropna().reset_index(drop=True)

    # --------------------- 特征工程 ---------------------
    # 定义特征和目标
    lag_features = [f'{target}_lag_{i}' for target in ['Temp1', 'Temp2'] for i in range(1, 4)]
    time_features = ['year', 'month', 'dow', 'dom', 'weekend']

    X = df[time_features + lag_features]
    y = df[['Temp1', 'Temp2']]  # 多目标输出

    # --------------------- 模型训练 ---------------------
    # 随机森林（多输出回归）
    rf_model = RandomForestRegressor(n_estimators=200,
                                     max_depth=7,
                                     random_state=42)
    multi_target_rf = MultiOutputRegressor(rf_model)
    multi_target_rf.fit(X, y)

    # --------------------- 未来预测 ---------------------
    def generate_predictions(model, last_known_data, steps=7):
        predictions = []
        current_data = last_known_data.copy()

        for _ in range(steps):
            # 将当前数据转换为DataFrame并设置列名
            current_df = pd.DataFrame([current_data[-1]], columns=X.columns)

            # 预测下一天
            pred = model.predict(current_df)[0]
            predictions.append(pred)

            # 更新数据窗口
            new_date = pd.to_datetime(current_data[-1]['Date']) + pd.Timedelta(days=1)
            new_row = {
                'Date': new_date,
                'year': new_date.year,
                'month': new_date.month,
                'dow': new_date.dayofweek,
                'dom': new_date.day,
                'weekend': int(new_date.dayofweek >= 5)
            }

            # 更新滞后特征
            for i in range(2, 0, -1):
                new_row[f'Temp1_lag_{i + 1}'] = current_data[-1][f'Temp1_lag_{i}']
                new_row[f'Temp2_lag_{i + 1}'] = current_data[-1][f'Temp2_lag_{i}']

            new_row['Temp1_lag_1'] = pred[0]
            new_row['Temp2_lag_1'] = pred[1]

            current_data = current_data[1:] + [new_row]

        return np.array(predictions)

    # 准备初始数据（最后3天的数据）
    last_3_days = []
    for i in range(-3, 0):
        record = {
            'Date': df['Date'].iloc[i],
            **{col: df[col].iloc[i] for col in X.columns}
        }
        last_3_days.append(record)

    # 生成预测
    predictions = generate_predictions(multi_target_rf, last_3_days)

    # --------------------- 结果处理 ---------------------
    future_dates = pd.date_range(
        start=df['Date'].max() + pd.Timedelta(days=1),
        periods=7
    )

    result_df = pd.DataFrame({
        'Date': future_dates,
        'Predicted_Temp1': predictions[:, 0],
        'Predicted_Temp2': predictions[:, 1]
    })

    # --------------------- 可视化 ---------------------
    plt.figure(figsize=(15, 8))
    plt.plot(df['Date'], df['Temp1'], 'b-', label='历史最高温')
    plt.plot(df['Date'], df['Temp2'], 'r-', label='历史最低温')
    plt.plot(result_df['Date'], result_df['Predicted_Temp1'], 'bo--',
             label='预测最高温')
    plt.plot(result_df['Date'], result_df['Predicted_Temp2'], 'ro--',
             label='预测最低温')
    plt.title('温度预测对比（未来7天）', fontsize=16)
    plt.xlabel('日期', fontsize=12)
    plt.ylabel('温度(℃)', fontsize=12)
    plt.xticks(rotation=45)
    plt.legend()
    plt.grid(True)
    plt.savefig('temperature_forecast.png')
    plt.close()


    return result_df.to_dict(orient='records')


# # 执行预测
# if __name__ == "__main__":
#     predictions = predict_weather()
#     print(predictions)